package org.datascooter.bundle.attribute;

import java.lang.reflect.Field;

import org.datascooter.exception.DataScooterException;

/**
 * Purpose for define entities contained into other entities in runtime. Store with special cross table for handle links between entities as distinct from PersistableChildBundle purposed for the same
 * operations but with particular link method through foreign keys
 * 
 * @author nemo
 * 
 */
public class FieldContainerAttribute extends ContainerAttribute {

	private Field field;

	/**
	 * Purposed for a mapping of a contained entities Parameter entity - may be String or Class
	 * 
	 */
	public FieldContainerAttribute(String name, String entity, String mapKeyAttribute, PersistencePolicy policy, boolean embedded, boolean fetchLazy) {
		super(name);
		this.entity = entity;
		this.mapKeyAttribute = mapKeyAttribute;
		this.policy = (policy == null ? PersistencePolicy.ALL : policy);
		this.embedded = embedded;
		this.fetchLazy = fetchLazy;
	}

	@Override
	public void explore(Class<?> clazz) {
		if (clazz != null) {
			Class<?> clazz1 = clazz;
			while (field == null) {
				try {
					field = clazz1.getDeclaredField(name);
				} catch (Exception e) {
					clazz1 = clazz1.getSuperclass();
					if (clazz1 == null) {
						throw new DataScooterException("***No field found  " + e.getMessage());
					}
				}
			}
			returnType = field.getType();
			field.setAccessible(true);
			setGetClass(returnType);
			setSetClass(returnType);
		}
	}

	@Override
	public <T> Object getValue(Object obj) throws IllegalArgumentException, IllegalAccessException {
		return field.get(obj);
	}

	@Override
	public void setValue(Object obj, Object value) throws IllegalArgumentException, IllegalAccessException {
		field.set(obj, value);
	}

	@SuppressWarnings("unchecked")
	@Override
	public FieldContainerAttribute copy() {
		return new FieldContainerAttribute(name, entity, mapKeyAttribute, policy, embedded, fetchLazy);
	}
}
